package com.chb.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.chb.app.config.TtlQueueConfig;
import com.chb.app.mapper.*;
import com.chb.app.service.PayService;
import com.chb.app.utils.HttpClient;
import com.chb.app.vo.PayDto;
import com.github.wxpay.sdk.WXPayUtil;
import com.hos.entity.his.*;
import com.hos.utils.IdGeneratorUtil;
import com.hos.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: 陈海彬
 * @date: Created in 2023/12/22 11:56
 * @description:
 * @modified By:
 * @version:
 */
@Service
@Slf4j
public class PayServiceImpl implements PayService {

    @Value("${weixin.appid}")
    private String appId;

    @Value("${weixin.mch_id}")
    private String mchId;

    @Value("${weixin.api_key}")
    private String apiKey;
    @Resource
    private CareHistoryMapper careHistoryMapper;
    @Resource
    private CareOrderMapper careOrderMapper;
    @Resource
    private CareOrderItemMapper careOrderItemMapper;
    @Resource
    private OrderChargeMapper orderChargeMapper;
    @Resource
    private OrderChargeItemMapper orderChargeItemMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Resource
    private RabbitTemplate rabbitTemplate;

    @Override
    public void getPayMock(String chId) {
        // 1.查询病例信息
        CareHistory careHistory = this.careHistoryMapper.selectById(chId);
        // 2.查询处方列表
        List<CareOrder> careOrders = this.selectCareOrderListByChId(chId);
        // 获取总费用
        BigDecimal orderAmount = careOrders.stream().map(CareOrder::getAllAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 创建收费列表
        OrderCharge orderCharge = this.insertOrderCharge(careHistory, orderAmount, "1", null, "0");
        // 创建收费详情列表
        Integer num = this.insertOrderItemCharge(careOrders, orderCharge, "1");
    }

    @Override
    public Result<PayDto> wxPay(String chId) {
        // 1.查询病例信息
        CareHistory careHistory = this.careHistoryMapper.selectById(chId);
        // 2.查询处方列表
        List<CareOrder> careOrders = this.selectCareOrderListByChId(chId);
        System.out.println(careOrders);
        // 获取总费用
        BigDecimal orderAmount = careOrders.stream().map(CareOrder::getAllAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        log.error("总费用" + orderAmount);
        // 创建收费列表
        OrderCharge orderCharge = this.insertOrderCharge(careHistory, orderAmount, "0", null, "2");
        String orderId = orderCharge.getOrderId();  // 訂單id
        // 创建支付二维码
        PayDto navite = this.createNavite(orderId, orderAmount);

        // 创建收费详情列表
        Integer num = this.insertOrderItemCharge(careOrders, orderCharge, "0");

        // 存入消息队列中
        MessageProperties messageProperties = new MessageProperties();
        messageProperties.setMessageId(orderId);
        // messageProperties.setExpiration("60000");
        Message message = new Message(orderId.getBytes(), messageProperties);
        rabbitTemplate.convertAndSend(TtlQueueConfig.ORDER_EXCHANGE, "", message);

        return new Result<>(200, "创建二维码成功", navite);
    }

    private OrderCharge selectOrderChargeByChId(String chId) {
        LambdaQueryWrapper<OrderCharge> wrapper = new LambdaQueryWrapper<>();

        wrapper.eq(OrderCharge::getChId, chId);
        return this.orderChargeMapper.selectOne(wrapper);
    }

    @Override
    public Result<String> queryWxPayStatus(String orderId) {
        try {
            // 1.根据订单状态查询微信的支付情况
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
            Map<String, String> params = new HashMap<>();
            params.put("appid", appId);             // 服务商的APPID
            params.put("mch_id", mchId);            // 商户号
            params.put("out_trade_no", orderId);    // 商户订单号
            params.put("nonce_str", WXPayUtil.generateNonceStr());  //  随机字符串

            client.setHttps(true);
            client.setXmlParam(WXPayUtil.generateSignedXml(params, apiKey));
            client.post();

            String content = client.getContent();
            Map<String, String> map = WXPayUtil.xmlToMap(content);
            if ("SUCCESS".equals(map.get("trade_state"))) {
                log.info("支付状态：" + map.get("trade_state"));
                // 1.修改订单状态
                OrderCharge orderCharge = this.updateOrderCharge(orderId, map.get("transaction_id"));
                // 2.修改子项的状态
                this.updateOrderChargeItem(orderCharge, "1");
                // 3.修改原来的状态
                this.updateCareOrderItem(orderCharge.getChId());
                return new Result<>(200, "支付成功", "");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new Result<>(500, "支付失败", "");
    }


    /**
     * @param chId
     * @create by: 陈海彬
     * @description: 修改原来的订单状态
     * @create time: 2023/12/29 10:29
     */
    private void updateCareOrderItem(String chId) {
        LambdaQueryWrapper<CareOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CareOrder::getChId, chId);
        List<CareOrder> careOrders = this.careOrderMapper.selectList(wrapper);
        for (CareOrder careOrder : careOrders) {
            LambdaUpdateWrapper<CareOrderItem> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper
                    .eq(CareOrderItem::getCoId, careOrder.getCoId())
                    .set(CareOrderItem::getStatus, "1");
            this.careOrderItemMapper.update(null, updateWrapper);
        }
    }


    /**
     * @param orderCharge 订单
     * @param status      状态 0为支付 1已支付 2 已退费 3已完成
     * @create by: 陈海彬
     * @description: 修改订单支付子项的状态
     * @create time: 2023/12/29 9:39
     */
    private void updateOrderChargeItem(OrderCharge orderCharge, String status) {
        LambdaUpdateWrapper<OrderChargeItem> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(OrderChargeItem::getOrderId, orderCharge.getOrderId())
                .set(OrderChargeItem::getStatus, status);
        this.orderChargeItemMapper.update(null, wrapper);
    }

    /**
     * @param orderId       病例id
     * @param transactionId 支付id  微信--支付宝支付id
     * @return com.hos.entity.his.OrderCharge
     * @create by: 陈海彬
     * @description: 修改支付状态
     * @create time: 2023/12/29 9:34
     */
    private OrderCharge updateOrderCharge(String orderId, String transactionId) {
        // 1.修改支付的状态
        LambdaUpdateWrapper<OrderCharge> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(OrderCharge::getOrderId, orderId)
                .set(OrderCharge::getPayPlatformId, transactionId)
                .set(OrderCharge::getOrderStatus, "1")
                .set(OrderCharge::getUpdateTime, new Date());
        this.orderChargeMapper.update(null, wrapper);

        // // 2.查询支付的项目
        // LambdaQueryWrapper<OrderCharge> queryWrapper = new LambdaQueryWrapper<>();
        // queryWrapper.eq(OrderCharge::getOrderId, orderId);
        return this.orderChargeMapper.selectById(orderId);
    }

    /**
     * @param careOrders  处方列表
     * @param orderCharge 收费表
     * @param status      0未支付，1已支付，2，已退费  3，已完成
     * @return 影响的行数
     * @create by: 陈海彬
     * @description: 订单收费详情子项列表
     * @create time: 2023/12/22 16:24
     */
    private Integer insertOrderItemCharge(List<CareOrder> careOrders, OrderCharge orderCharge, String status) {
        int num = 0;
        for (CareOrder careOrder : careOrders) {
            // 3.查询子检测项目
            List<CareOrderItem> orderItems = this.selectCareOrderItemListByChId(careOrder.getCoId());
            // 4.进行添加收费子项
            for (CareOrderItem orderItem : orderItems) {
                // 修改收费状态
                orderItem.setStatus(status);
                OrderChargeItem orderChargeItem = new OrderChargeItem();
                // 设置详情id
                // orderChargeItem.setItemId(IdGeneratorUtil.nextId("ITEM"));
                orderChargeItem.setItemId(orderItem.getItemId());
                // 设置处方id
                orderChargeItem.setCoId(orderItem.getCoId());
                // 设置项目名称
                orderChargeItem.setItemName(orderItem.getItemName());
                // 设置项目价格
                orderChargeItem.setItemPrice(orderItem.getPrice());
                // 设置项目数量
                orderChargeItem.setItemNum(orderItem.getNum());
                // 设置小计
                orderChargeItem.setItemAmount(orderItem.getAmount());
                // 设置订单id
                orderChargeItem.setOrderId(orderCharge.getOrderId());
                // 设置项目类型
                orderChargeItem.setItemType(orderItem.getItemType());
                // 设置支付状态 0 未支付 1已支付 2已退费 3已完成
                orderChargeItem.setStatus("1");
                // 修改支付状态
                this.careOrderItemMapper.updateById(orderItem);
                num += this.orderChargeItemMapper.insert(orderChargeItem);
            }
        }
        return num;
    }

    /**
     * @param careHistory 病例表
     * @param orderAmount 总费用
     * @param orderStatus 0未支付  1 支付成功  2支付超时 3支付失败
     * @param payId       支付id
     * @param payType     支付类型 0现金 1支付宝 2微信
     * @return com.hos.entity.his.OrderCharge
     * @create by: 陈海彬
     * @description: 创建收费id
     * @create time: 2023/12/22 16:14
     */
    private OrderCharge insertOrderCharge(CareHistory careHistory, BigDecimal orderAmount, String orderStatus, String payId, String payType) {
        OrderCharge orderCharge = new OrderCharge();
        // 生成收费id
        String odcId = IdGeneratorUtil.nextId("ODC");
        orderCharge.setOrderId(odcId);
        // 设置总费用
        orderCharge.setOrderAmount(orderAmount);
        // 设置病例id
        orderCharge.setChId(careHistory.getChId());
        // 设置挂号id
        orderCharge.setRegId(careHistory.getRegId());
        // 设置患者名称
        orderCharge.setPatientName(careHistory.getPatientName());
        // 设置订单状态 1 支付成功  0 未支付
        orderCharge.setOrderStatus(orderStatus);
        orderCharge.setPayPlatformId(payId);
        // 设置支付时间
        orderCharge.setPayTime(new Date());
        // 设置支付类型  0现金 1支付宝 2微信
        orderCharge.setPayType(payType);
        // 设置创建时间
        orderCharge.setCreateTime(new Date());
        // 设置更新时间
        orderCharge.setUpdateTime(new Date());
        // 设置创建者
        orderCharge.setCreateBy("超级管理员");

        // 进行添加收费
        this.orderChargeMapper.insert(orderCharge);
        return orderCharge;
    }

    /**
     * @param coId 处方id
     * @return java.util.List<com.hos.entity.his.CareOrder>
     * @create by: 陈海彬
     * @description: 查询处方列表
     * @create time: 2023/12/22 15:42
     */
    private List<CareOrderItem> selectCareOrderItemListByChId(String coId) {
        LambdaQueryWrapper<CareOrderItem> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CareOrderItem::getCoId, coId);
        return this.careOrderItemMapper.selectList(wrapper);
    }


    /**
     * @param orderId 病例信息
     * @param price   价格
     * @return com.chb.app.vo.PayDto
     * @create by: 陈海彬
     * @description: 创建微信成二维码
     * @create time: 2023/12/29 9:20
     */
    public PayDto createNavite(String orderId, BigDecimal price) {
        // 设置请求的参数————格式为xml格式
        Map<String, String> params = new HashMap<>();
        params.put("appid", appId);   // 公众号
        params.put("mch_id", mchId);  // 商户号
        params.put("nonce_str", WXPayUtil.generateNonceStr());      // 32位随机字符串
        params.put("body", "嘉会医疗处方收费");                 // 商品描述
        params.put("out_trade_no", orderId);                        // 商户订单号
        // params.put("total_fee", new BigDecimal(order.getTotalFee().multiply(new BigDecimal(100)).longValue()) + "");
        params.put("total_fee", "1");  // 设置金额
        params.put("spbill_create_ip", "127.0.0.1");    // 未来写成项目部署的ip
        params.put("notify_url", "http://localhost:9000/pay/back");  // 回调地址
        params.put("trade_type", "NATIVE");                          // 交易类型

        try {
            // 2.创建HttpClient对象 作为远程调用
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
            // 支持http协议
            client.setHttps(true);
            client.setXmlParam(WXPayUtil.generateSignedXml(params, apiKey));
            // 发送请求
            client.post();

            // 获得响应对象
            String content = client.getContent();

            Map<String, String> map = WXPayUtil.xmlToMap(content);
            if ("SUCCESS".equals(map.get("result_code"))) {
                String codeUrl = map.get("code_url");
                return new PayDto(codeUrl, price, orderId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new PayDto();
    }

    /**
     * @param chId 病例id
     * @return java.util.List<com.hos.entity.his.CareOrder>
     * @create by: 陈海彬
     * @description: 查询处方列表
     * @create time: 2023/12/22 15:42
     */
    private List<CareOrder> selectCareOrderListByChId(String chId) {
        LambdaQueryWrapper<CareOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CareOrder::getChId, chId);
        return this.careOrderMapper.selectList(wrapper);
    }

}